home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
LIBRARY
/
PBLIB1
/
DOC
/
MYOBJS.DOC
< prev
next >
Wrap
Text File
|
1994-04-30
|
11KB
|
279 lines
\space 20
\CENTER on
Howard's OBJECTS
\space 20
\CENTER off
\indent 30
\source howard.adr
\indent 0
\new
\CENTER Introduction
\join on
I am a medium old-fashioned programmer. I started 25 years ago,
and programmed for a living on more systems and in more languages than I
like to remember. I learned not to use GOTOs, but somewhere in the 80s
I stopped getting excited about new programming techniques and concentrated
on simply making things that worked.
Turbo Pascal is the best all-around language I have ever used. When
they introduced Units, it really marked the end of the monolithic program,
and made it practical to re-use code. The concept of Objects leaped beyond
units, but somewhere around "virtual methods" it lost me.
My use of objects is both primitive and extremely useful. I focus
on the ability of an object to encapsulate code and data, making complex
functions appear to be simple. One of the things that was always difficult
prior to objects, was coding the second instance of whatever. It was
straight-forward to code, say, the first use of a .dbf file in your
program, but adding a second always involved global variables which had
to be used simultaneously to track two different things. Making the code
into an object allowed simultaneous use almost trivially.
An object is also the best place to hide truely ugly code. We all
have it. There are things that simply need to be done quickly, with
cleanup later (hopefully). I hope that the ugliest of the code is
gone before I release these objects and utilities for the first time,
but if not, I apologize in advance.
\new
\CENTER Personal Bias
Code is personal, and reflects the biases of the author. I have
a few, and I will try to explain them.
\join off
1. Efficient code is nice, but not terribly important. I try not to
waste CPU cycles, but hardware gets better by a factor of 2 each
year, and I improve by maybe 10%. The choice is obvious.
2. Code size and EXE size is a little more important, but again, not
critical. With all the configuration and output support routines,
my "Hello world." size is around 15k. A seriously useful utility
can be written in 100 lines or so of non-library code and take
>25k. To me, this is good. I have done what I can to keep the
size down, but I think the situation is about optimum now. I welcome
improvements down at the lowest level because they give the
greatest returns, but thorough testing is in order.
3. I use minimum comments in the code. My preference is to name
routines and variables sensibly, and only document the subtle
points. Comments on code lines tend to hide structure.
4. My development system is a 486DX2-66, 16Mb ram, 450Mb disk and
LaserJet IV printer. I have access to smaller systems, but my
smallest is a 386-40. Obviously, this affects my code. Most
specifically are instances of sending LJ escape sequences to
the printer. I hope to cut out and make optional, all printer
specific strings, but the first release may still have some.
\new
\center 'On To Objects'
\join off
The Objects which I use most are as follows:
1. STR_object - consists of a Pascal string (1-255 chars) allocated
from the Heap. Can be stored or fetched. Not too exciting.
2. STRA_object - an array of STR_objects, with the strings and pointers
all on the Heap. This feels a lot like a text file in memory.
Can store and fetch randomly or sequentially. Can be searched
and sorted. Useful as a memory image of a text file or a
list of things like file names. Can be saved to disk or loaded
from disk. Looks like:
Index STRING
1 xxxxxxxxx
2 yyyyy
3 zzzzz
...
I have not fully examined the limits. I suspect either the
index or the strings or something is limited to 64k. I have
chosen 10,000 as a compiled in limit. When initting the object
an actual allocation limit less than that is chosen for each
instance. I have loaded a 173,900 byte text file (3674 lines)
into a STRA. It used slightly over 200kbytes of heap when the
initialization was set to 3700. Empty array initialization
averages 12 bytes per string, but some is recovered in use.
All-in-all, this is an extremely useful construct, especially
in some of its descendant forms.
3. HOLD_object - descendent of STRA_object. Adds and array of longints
which travel with each string.
Index STRING NUM
1 xxxxxxxxx 123456
2 yyyyy 1
3 zzzzz 999999
...
If the string array is sorted, the num value moves along with
it, making the list good for things like pointers to sections
in a text file (HELP_object, SORTSECT).
4. FILE_object - an encapsulation of the binary file I/O, blockread,
blockwrite code. I haven't used this too much.
5. TFILE_object - an encapsulation of TEXT file I/O. This is central
to virtually every program I write. I find it much more
friendly than straight Pascal code. Important here is the
implementation of some PD code for random access - TEXTSEEK.
6. OUT_object - I have been aiming towards this for years. I wanted:
1. Hide the bookkeeping for list output, headers, footers
line numbers, page numbers.
2. Have a program be able to interchangeably, but intelligently
switch between output to the CRT, PRINTER or a TEXT file.
This is things like pausing when output is to the
CRT, form feeds to the printer, and saving output to
text files.
3. Control these options with run time parameters, and hide
virtually all of it from the program which uses it.
After constructing the OUT_object, I found that it added
8k or so to even very simple programs which didn't need
all the frills. I then divided it into two levels, 0 & 1
and hid this further into two libraries OUTLIB0 and OUTLIB1.
The level 0 object only adds about 4k per program. So a
program can start with outlib0 (no headers, footers and
word-wrap), and by changing to uses outlib1, can trivially
add the headers etc.
7. HELP_object - Needs a better name, but I wrote it to implement HELP
files. This is basicly a text file with random access to
sections of the file. The sections can be pretty flexibly
designated, some constant string at the beginning of the
line followed by a name string.
8. DBF_object - Not quite ready for publication. Started out with a
bit of PD code for reading DBF files (Gerald Rohr). Worked
out most of header, and file structure and encapsulated as
DBF_object. Couldn't make heads nor tails of .NDX files, so
I used a string array descendent (STRX) to make indexing
easy. KEYED_DBF_object handles multiple key files and multiple
and partial key fields. I used this as the basis for a group
of utilites consolidated into DB.exe to DUMP, CLONE, SORT
EXPORT, CREATE, and DDL(show structure). A few small missing
pieces yet.
9. BITMAP_object - I haven't used this in a couple of years. It was
a large virtual bit-map, using heap in memory and loadable
and saveable to disk.
\NEW
\CENTER STR_object - 1. String on Heap - Detail
Here is the interface to the STR_object:
{source \hnrlib\hnrobjs.pas(.str_object)}
\source \hnrlib\hnrobjs.pas(.str_object)
The data for the object consists of a pointer to a string on the heap.
\NEW
\CENTER STRA_object - 2. String Array - Detail
Here is the interface to the STRA_object:
{source \hnrlib\hnrobjs.pas(.STRA_object)}
\source \hnrlib\hnrobjs.pas(.STRA_object)
\join
As you can see, this is rather a "kitchen sink" object. The compiler
does a good job pruning unused methods, and I don't have any good tools
for examining just which functions I have never used. The sort is a nice
shell sort I located in PD code, and is fast.
I have been bashing STRA around with some new test code, and it stands
up well. It doesn't leave any grabage on the heap. Being in heap space,
it is easy to pass as a parameter between routines - stack friendly. When I
crank down the heap limits and let the object bump into them, there are
some irregularities I need to track down.
\join off
\NEW
\CENTER HOLD_object - 3. String & Longint Array - Detail
Here is the interface to the HOLD_object:
{source \hnrlib\hnrobjs.pas(.HOLD_object)}
\source \hnrlib\hnrobjs.pas(.HOLD_object)
\NEW
\CENTER FILE_object - 4. Binary File Encapsulation - Detail
Here is the interface to the FILE_object:
{source \hnrlib\hnrobjs.pas(.FILE_object)}
\source \hnrlib\hnrobjs.pas(.FILE_object)
\NEW
\CENTER TFILE_object - 5. TEXT File Encapsulation - Detail
Here is the interface to the TFILE_object:
{source \hnrlib\hnrobjs.pas(.TFILE_object)}
\source \hnrlib\hnrobjs.pas(.TFILE_object)
\NEW
\CENTER OUT_object_0 - 6a. OUTPUT Encapsulation - Detail
Here is the interface to the OUT_object (level 0):
{source \hnrlib\hnrobjs.pas(.OUT_object_0)}
\source \hnrlib\hnrobjs.pas(.OUT_object_0)
\NEW
\CENTER OUT_object_1 - 6b. OUTPUT Encapsulation - Detail
Here is the interface to the OUT_object (level 1):
{source \hnrlib\hnrobjs.pas(.OUT_object_1)}
\source \hnrlib\hnrobjs.pas(.OUT_object_1)
\NEW
\CENTER HELP_object - 7. Sectioned TEXT File - Detail
Here is the interface to the HELP_object:
{source \hnrlib\hnrobjs.pas(.HELP_object)}
\source \hnrlib\hnrobjs.pas(.HELP_object)
\NEW
\CENTER DBF_object - 8. DBase DBF File Encapsulation - Detail
Here is the interface to the DBF_object:
{source \hnrlib\hnrobjs.pas(.DBF_object)}
\source \hnrlib\hnrobjs.pas(.DBF_object)
The really ugly code is down one or two levels in DBLKstuf and
XBASstuf, and best that it remain there. I am not using this heavily
at present, but it tests well and is easy to code with. The utility
DBPASgen generates a nice shell around the KEYED_DBF_object so that
the interface is a Pascal record structure, and it is not necessary
go into DBASE world. This topic will get a paper of its own, for
more detail. It is included here to show that objects can be pretty
high level constructs as well as small building blocks.
\NEW
\CENTER BITMAP_object - 9. BitMap 1 - 65000 bits - Detail
Here is the interface to the BITMAP_object:
{source \hnrlib\bitstuf.pas(.BITMAP_object)}
\source \hnrlib\bitstuf.pas(.BITMAP_object)}